/**
 * 
 */
package com.vision.core.sv.serv;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.vision.core.cm.data.AdminPermissions;
import com.vision.core.cm.db.data.Company;
import com.vision.core.cm.db.data.Company.CompanyStatus;
import com.vision.core.cm.db.data.CompanyGroup;
import com.vision.core.cm.db.data.Permission;
import com.vision.core.cm.db.data.Role;
import com.vision.core.cm.db.data.User;
import com.vision.core.cm.db.data.User.UserStatus;
import com.vision.core.sv.db.CustomSessionFactoryBean;
import com.vision.core.sv.db.mgr.CompanyGroupManager;
import com.vision.core.sv.db.mgr.CompanyManager;
import com.vision.core.sv.db.mgr.PermissionManager;
import com.vision.core.sv.db.mgr.RoleManager;
import com.vision.core.sv.db.mgr.UserManager;
import com.vision.core.sv.security.Encrypt;

/**
 * TODO For local deployments, we might have to remove this for security reasons.
 * 
 * @author Mark
 *
 */
public class DatabaseInitializerServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	
	private static final Logger log = LoggerFactory.getLogger(DatabaseInitializerServlet.class);
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		
		try {
			if (!isDatabaseInitialized()) {
				log.info("Database is not yet initialized. Initializing database...");
				initializeDatabase();
				log.info("Database successfully initialized.");
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new ServletException("Error initializing the database.", e);
		}
	}
	
	protected boolean isDatabaseInitialized() throws SQLException {
		SessionFactory sf = CustomSessionFactoryBean.getFactory();
		UserManager userManager = new UserManager();
		userManager.setSessionFactory(sf);
		return !userManager.getAll().isEmpty();
	}
	
	protected void initializeDatabase() {
		SessionFactory sf = CustomSessionFactoryBean.getFactory();

		// Companies %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		CompanyManager companyManager = new CompanyManager();
		companyManager.setSessionFactory(sf);
		
		Company vision = new Company();
		vision.setCode("VTLC");
		vision.setName("Vision Tapes & Labels Corp.");
		vision.setAddress("322 A. Bonifacio St., Quezon City");
		vision.setStatus(CompanyStatus.ACTIVE);
		companyManager.create(vision);
		
		Company allStik = new Company();
		allStik.setCode("ASPC");
		allStik.setName("All Stik Trading Corp.");
		allStik.setAddress("322 A. Bonifacio St., Quezon City");
		allStik.setStatus(CompanyStatus.ACTIVE);
		companyManager.create(allStik);
		
		Set<Company> allCompanies = new HashSet<Company>();
		allCompanies.add(vision);
		allCompanies.add(allStik);
		
		// Company Groups %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		CompanyGroupManager companyGroupManager = new CompanyGroupManager();
		companyGroupManager.setSessionFactory(sf);
		
		{
			companyGroupManager.create(new CompanyGroup(vision, "C"));
			companyGroupManager.create(new CompanyGroup(vision, "L"));
			companyGroupManager.create(new CompanyGroup(vision, "Y"));
			
			companyGroupManager.create(new CompanyGroup(allStik, "S"));
			companyGroupManager.create(new CompanyGroup(allStik, "X"));
		}
		
		// Permissions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		PermissionManager permissionManager = new PermissionManager();
		permissionManager.setSessionFactory(sf);
		
		for (Permission permission : AdminPermissions.All) {
			permissionManager.create(permission);
		}
		
		
		// Roles *************************************
		RoleManager roleManager = new RoleManager();
		roleManager.setSessionFactory(sf);
		
		Role rootRole = new Role();
		rootRole.setName(Role.ROOT_NAME);
		rootRole.setDescription("System root role. Can perform all operations.");
		rootRole.setPermissionsFromArray(AdminPermissions.All);
		roleManager.create(rootRole);
		
		Role userEncoder = new Role();
		userEncoder.setName("User Encoder");
		userEncoder.setDescription("Has privileges to encode users.");
		userEncoder.setPermissions(AdminPermissions.AllForUser);
		roleManager.create(userEncoder);
		
		// Users ***********************************
		UserManager userManager = new UserManager();
		userManager.setSessionFactory(sf);
		
		User root = new User();
		root.setUsername(User.ROOT_USERNAME);
		root.setPassword(Encrypt.encode("root"));
		root.setEmail("markrgli@gmail.com");
		root.setFirstName("System");
		root.setLastName("User");
		root.setDateCreated(new Timestamp(System.currentTimeMillis()));
		root.setStatus(UserStatus.ACTIVE);
		root.setCompanies(allCompanies);
		root.addRole(rootRole);
		userManager.create(root);
		
		User admin = new User();
		admin.setUsername("markitol");
		admin.setPassword(Encrypt.encode("markitol"));
		admin.setEmail("markitol1985@gmail.com");
		admin.setFirstName("Mark RG");
		admin.setLastName("Itol");
		admin.setDateCreated(new Timestamp(System.currentTimeMillis()));
		admin.setStatus(UserStatus.ACTIVE);
		Set<Company> visionOnly = new HashSet<Company>();
		visionOnly.add(vision);
		admin.setCompanies(visionOnly);
		admin.addRole(userEncoder);
		userManager.create(admin);
	}

}
